from typing import Dict

import chromadb
from elasticsearch import Elasticsearch

from home.models import Jobposting
from rag.emm.text_rag import TextEmbedding
from user.models import City


def fetch_job(limit: int = 1000):
    """
    获取岗位信息  N+1
    """

    working_dict = {
        "0": "经验不限",
        "1": "在校生",
        "2": "应届生",
        "3": "1-3年",
        "4": "3-5年",
        "5": "5年以上"
    }
    qs = Jobposting.objects.select_related('city', 'company').all()
    qs = qs[:limit]
    job_list = []
    for job in qs:
        job_list.append(
            {
                "id": str(job.id),
                "title": job.title,
                "company": job.company.name,
                "city": job.city.name,
                "description": job.description,
                "label": job.label,
                "education": job.education,
                "working": working_dict.get(job.education)

            }
        )
    return job_list


def build_searchable_text_from_job(job) -> str:
    """
    基于 Jobposting 实例构造可检索字段 searchable_text（极简版）。
    选取：title、description、label、education、jobcate.name（若有）按行拼接。
    """
    title = job.title
    desc = job.description
    label = job.label
    edu = job.education
    city = job.city
    working = job.working
    job_str = f"""
    职位名称:{title},
    职位描述:{desc},
    职位标签:{label},
    职位学历:{edu},
    职位城市:{city},
    工作经验:{working}


    """

    return job_str


def job_es_index(index_name: str):
    """
     es:index索引
     先创建一个索引库
     索引库设计字段,增加数据
    """
    es_client = Elasticsearch("127.0.0.1")
    if not es_client.indices.exists(index=index_name):
        es_client.indices.create(index=index_name)

    # 创建索引字段映射
    body = {
        "mappings": {
            "properties": {
                "id": {
                    "type": "keyword"
                },
                "title": {
                    "type": "keyword"
                },
                "company": {
                    "type": "keyword"
                },
                "city": {
                    "type": "keyword"
                },
                "description": {
                    "type": "text"
                },
                "label": {
                    "type": "keyword"
                },
                "education": {
                    "type": "keyword"
                },
                "job_str": {
                    "type": "text"
                }
            }
        }
    }
    es_client.indices.create(index=index_name, body=body)


def job_es_add(index_name: str, job_list: list):
    """
    添加数据
    """
    es_client = Elasticsearch("127.0.0.1")
    job_list = fetch_job()
    for job in job_list:
        job_str = build_searchable_text_from_job(job)
        doc = {
            "id": job.id,
            "title": job.title,
            "company": job.company.name,
            "city": job.city.name,
            "description": job.description,
            "label": job.label,
            "education": job.education,
            "job_str": job_str
        }
        es_client.index(index=index_name, id=job.id, document=doc, refresh=False)
    es_client.indices.refresh(index=index_name)


def job_with_text_embedding(job_list: list) -> list[Dict[str, object]]:
    """
    把岗位信息转化成向量
    [[],[],[]]
    [{"id":[1024]},{"":[]}]
    """
    job_text_embedding_list = []
    for job in job_list:
        job_str = build_searchable_text_from_job(job)
        textEmbedding = TextEmbedding()
        job_text_embedding = textEmbedding.generate_embeddings(job_str)
        job_text_embedding = {
            "id": job.id,
            "text_embedding": job_text_embedding,
            "job_str": job_str
        }
        job_text_embedding_list.append(job_text_embedding)

    return job_text_embedding_list


def sync_jobs_to_chroma(job_text_embedding_list: list[Dict[str, object]]):
    """
    把向量存储到chromaDB
    """

    client = chromadb.PersistentClient(path="./chromadb_db")
    col = client.get_or_create_collection(name="job_text_embedding", embedding_function=None)

    col.add(
        embeddings=[job_text_embedding_list["text_embedding"] for item in job_text_embedding_list],
        ids=[job_text_embedding_list["id"] for item in job_text_embedding_list],
        documents=[job_text_embedding_list["job_str"] for item in job_text_embedding_list]
    )


def hybrid_search_jobs(query: str, top_k: int = 8) -> list[Dict]:
    """
    混合搜索岗位：结合向量搜索和关键词搜索
    """
    try:
        # 向量搜索
        vector_results = vector_search_jobs(query, top_k)
        
        # 关键词搜索
        keyword_results = keyword_search_jobs(query, top_k)
        
        # 合并结果并去重
        combined_results = []
        seen_ids = set()
        
        # 优先添加向量搜索结果
        for result in vector_results:
            if result['id'] not in seen_ids:
                combined_results.append(result)
                seen_ids.add(result['id'])
        
        # 添加关键词搜索结果
        for result in keyword_results:
            if result['id'] not in seen_ids and len(combined_results) < top_k:
                combined_results.append(result)
                seen_ids.add(result['id'])
        
        return combined_results[:top_k]
        
    except Exception as e:
        print(f"混合搜索出错: {e}")
        # 降级到简单的关键词搜索
        return keyword_search_jobs(query, top_k)


def vector_search_jobs(query: str, top_k: int = 8) -> list[Dict]:
    """
    基于向量的岗位搜索
    """
    try:
        client = chromadb.PersistentClient(path="./chromadb_db")
        col = client.get_or_create_collection(name="job_text_embedding", embedding_function=None)
        
        # 检查集合是否为空
        collection_count = col.count()
        if collection_count == 0:
            print("ChromaDB集合为空，请先导入职位数据")
            return []
        
        # 生成查询向量
        textEmbedding = TextEmbedding()
        query_embedding = textEmbedding.generate_embeddings(query)
        
        # 向量搜索
        results = col.query(
            query_embeddings=[query_embedding],
            n_results=top_k
        )
        
        # 格式化结果 - 从实际数据中获取信息
        job_results = []
        if results['ids'] and results['ids'][0]:
            for i, job_id in enumerate(results['ids'][0]):
                # 从文档中解析职位信息
                document = results['documents'][0][i] if results['documents'] and results['documents'][0] else ''
                
                # 简单的解析逻辑，从文档文本中提取信息
                job_info = {
                    'id': job_id,
                    'title': '未知职位',
                    'company': '未知公司',
                    'city': '未知城市',
                    'tags': '',
                    'searchable_text': document,
                    'score': results['distances'][0][i] if results['distances'] and results['distances'][0] else 0
                }
                
                # 尝试从文档中提取职位名称
                import re
                title_match = re.search(r'职位名称:([^,]+)', document)
                if title_match:
                    job_info['title'] = title_match.group(1).strip()
                
                company_match = re.search(r'公司:([^,]+)', document)
                if company_match:
                    job_info['company'] = company_match.group(1).strip()
                
                city_match = re.search(r'城市:([^,]+)', document)
                if city_match:
                    job_info['city'] = city_match.group(1).strip()
                
                job_results.append(job_info)
        
        return job_results
        
    except Exception as e:
        print(f"向量搜索出错: {e}")
        return []


def keyword_search_jobs(query: str, top_k: int = 8) -> list[Dict]:
    """
    基于关键词的岗位搜索
    """
    try:
        es_client = Elasticsearch("http://localhost:9200")
        index_name = "jobs"
        
        # 检查索引是否存在
        if not es_client.indices.exists(index=index_name):
            print(f"Elasticsearch索引 '{index_name}' 不存在，请先创建索引并导入职位数据")
            return []
        
        # 执行搜索
        search_body = {
            "query": {
                "multi_match": {
                    "query": query,
                    "fields": ["title", "description", "label", "job_str"],
                    "type": "best_fields"
                }
            },
            "size": top_k
        }
        
        response = es_client.search(index=index_name, body=search_body)
        
        # 格式化结果
        job_results = []
        for hit in response['hits']['hits']:
            source = hit['_source']
            job_results.append({
                'id': source.get('id', ''),
                'title': source.get('title', ''),
                'company': source.get('company', ''),
                'city': source.get('city', ''),
                'tags': source.get('label', ''),
                'searchable_text': source.get('job_str', ''),
                'score': hit['_score']
            })
        
        return job_results
        
    except Exception as e:
        print(f"关键词搜索出错: {e}")
        return []


